#ifndef __SMART_PTR_H__
#define __SMART_PTR_H__

#include <assert.h>

#include "SpinLock.h"
namespace share
{

/** Template simulates a "smart" pointer which deletes the item it is
    pointing to when no more references to the item exist.  Warning:
    circular references will produce memory leaks.

    <P>Note that only one Sptr should be constructed from the original
    ptr_ -- Sptr will free twice (and cause havoc) if it is misused like so:
    <P>
    <B> WRONG: </B>
    <PRE>
        T* obj = new T();
        Sptr<T> p;
        Sptr<T> q;
        p = obj;
        q = obj;
           <I>now both p and q think they are the only ones who will free the
              memory, so you will get an error.</i>
    </PRE>

*/

template < class T >
class Sptr
{
public:
	T* ptr_;
	int* count_;
	SpinLock* mutex_;

private:
	/// increment the reference count_.
	void increment( )
	{
		if( ptr_ )
		{
			if( !count_ )
			{
				count_ = new int ( 0 );
			}

			if( !mutex_ )
			{
				mutex_ = new SpinLock;
			}

			{
				mutex_->acquire( );
				( *count_ ) ++;
				mutex_->release( );
			}
		}
	}

	/// decrement the reference count_
	void decrement( )
	{
		if( ptr_ && count_ )
		{
			bool countIsZero;
			{
				mutex_->acquire( );
				( *count_ )--;
				countIsZero = ( *count_ == 0 );
				mutex_->release( );
			}

			if( countIsZero )
			{
				delete ptr_;
				ptr_ = 0;
				delete count_;
				count_ = 0;
				delete mutex_;
				mutex_ = 0;
			}
		}

		ptr_ = 0;
		count_ = 0;
		mutex_ = 0;
	}

public:
	/** conversion operator converts pointers of this class to
	* class Sptr< T2 >., where T2 is a different base class.  This
	* is most often used when attempting to call a method of the
	* base class through a derived class pointer.
		*/
	template < class T2 >
	operator Sptr<T2 > ( )
	{
		return Sptr < T2 > ( ptr_, count_, mutex_ );
	}

	/** conversion operator converts pointers of this const class
	* to class const Sptr< T2 >., where T2 is a different base
	* class.  This is most often used when attempting to call a
	* const method of the base class through a derived class
	* pointer.
	*/
	template < class T2 >
	operator const Sptr<T2 > ( ) const
	{
		return Sptr < T2 > ( ptr_, count_, mutex_ );
	}

	/// default constructor.  points to NULL.
	Sptr( ) : ptr_( 0 ), count_( 0 ), mutex_( 0 )
	{}
	;

	/** constructor used most often as the constructor from a
	* plain pointer.  Do not use this to convert a single pointer
	* to a smart pointer multiple times -- this will result in an
	* error (see class introduction for details).
	*/
	Sptr( T* original, int* myCount = 0, SpinLock* myMutex = 0 )
		: ptr_( original ), count_( myCount ), mutex_( myMutex )
	{
		if( ptr_ )
		{
			increment( );
		}
	};

	template <class T2>
	Sptr( const Sptr<T2>& x )
		: ptr_( x.ptr_ ), count_( x.count_ ), mutex_( x.mutex_ )
	{
		increment( );
	};

	/** copy constructor
	*/
	Sptr( const Sptr& x )
		: ptr_( x.ptr_ ), count_( x.count_ ), mutex_( x.mutex_ )
	{
		increment( );
	};

	/// destructor
	~Sptr( )
	{
		{
			decrement( );
		}
	}

	/// dereference operator
	T& operator*( ) const
	{
		assert( ptr_ );
		return *ptr_;
	}

	/// ! operator .  Returns true if ptr_ == 0, false otherwise.
	int operator!( ) const
	{
		if( ptr_ )
		{
			return ( ptr_ == 0 );
		}
		else
			return true;
	}

	/// pointer operator.
	T* operator-> ( ) const
	{
		return ptr_;
	}

	/** dynamicCast works similarly to the actual dynamic_cast()
	* operator, like so:

	  <PRE>
	     class A {
		 ...
		 };
		 class B : public A {
		 ...
		 };
		 class C {
		 ...
		 };
		 ...
		 int main()
		 {
		 Sptr< A > a;
		 Sptr< B > b;
		 Sptr< C > c;

		   a = new B;

			 b.dynamicCast(a);
			 // now, b points to the same thing as a

			   c.dynamicCast(a);
			   // now, c is the NULL pointer.
			   }
			   </PRE>
	*/
	template < class T2 > Sptr& dynamicCast( const Sptr < T2 > & x )
	{
		if( ptr_ == x.getPtr( ) ) return *this;

		decrement( );

		if( T* p = dynamic_cast < T* >( x.getPtr( ) ) )
		{
			count_ = x.getCount( );
			mutex_ = x.getMutex( );
			ptr_ = p;
			increment( );
		}

		return *this;
	}
	/** assignment operator -- this is most often used to assign
	* from a smart pointer to a derived type to a smart pointer
	* of the base type.
	*/
	template < class T2 >
	Sptr& operator= ( const Sptr < T2 > & x )
	{
		if( ptr_ == x.getPtr( ) ) return * this;

		decrement( );
		ptr_ = x.getPtr( );
		count_ = x.getCount( );
		mutex_ = x.getMutex( );
		increment( );
		return *this;
	}


	/** assignment operator from plain pointer.  Do not use this
	* to convert a single pointer to a smart pointer multiple
	* times -- this will result in an error (see class
	* introduction for details).
	*/
	Sptr& operator= ( T* original )
	{
		if( ptr_ == original ) return * this;

		decrement( );
		ptr_ = original;
		increment( );
		return *this;
	};

	/// assignment operator
	Sptr& operator= ( const Sptr& x )
	{
		if( ptr_ == x.getPtr( ) ) return * this;

		decrement( );
		ptr_ = x.ptr_;
		count_ = x.count_;
		mutex_ = x.mutex_;
		increment( );
		return *this;
	}

	/// compare whether a pointer and a smart pointer point to different things
	friend bool operator!= ( const void* y, const Sptr& x )
	{
		if( x.ptr_ != y )
			return true;
		else
			return false;
	}

	/// compare whether a smart pointer and a pointer point to different things
	friend bool operator!= ( const Sptr& x, const void* y )
	{
		if( x.ptr_ != y )
			return true;
		else
			return false;
	}

	/// compare whether a pointer and a smart pointer point to the same thing
	friend bool operator== ( const void* y, const Sptr& x )
	{
		if( x.ptr_ == y )
			return true;
		else
			return false;
	}

	/// compare whether a smart pointer and a pointer point to the same thing
	friend bool operator== ( const Sptr& x, const void* y )
	{
		if( x.ptr_ == y )
			return true;
		else
			return false;
	}

	/// compare whether two smart pointers point to the same thing
	bool operator== ( const Sptr& x ) const
	{
		if( x.ptr_ == ptr_ )
			return true;
		else
			return false;
	}

	/// compare whether two smart pointers point to different things
	bool operator!= ( const Sptr& x ) const
	{
		if( x.ptr_ != ptr_ )
			return true;
		else
			return false;
	}

	/**
	   this interface is here because it may sometimes be
	   necessary.  DO NOT USE unless you must use it.
	   get the actual mutex_ of the smart pointer.
	*/
	SpinLock* getMutex( ) const
	{
		return mutex_;
	}

	/**
	   this interface is here because it may sometimes be
	   necessary.  DO NOT USE unless you must use it.
	   get the value of the reference count_ of the smart pointer.
	*/
	int* getCount( ) const
	{
		return count_;
	}

	/**
	   this interface is here because it may sometimes be
	   necessary.  DO NOT USE unless you must use it.
	   get the pointer to which the smart pointer points.
	*/
	T* getPtr( ) const
	{
		return ptr_;
	}

};

}
#endif

